﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace InitiativeTracker
{
    class XMLHelper
    {
        XmlDocument document;
        private static XMLHelper _instance;
        XmlNode initiativeDateNode;
        Dictionary<string, List<XmlAttribute>> nodeDictionary;

        XMLHelper()
        {
            nodeDictionary = new Dictionary<string, List<XmlAttribute>>();
            ResetDocument();
        }

        public static XMLHelper Instance()
        {
            if (_instance == null)
            {
                _instance = new XMLHelper();
            }
            return _instance;
        }
        
        public void ResetDocument()
        {
            document = new XmlDocument();
            XmlNode docNode = document.CreateXmlDeclaration("1.0", "UTF-8", null);
            initiativeDateNode = document.CreateElement("InitiativeData");
            document.AppendChild(docNode);
        }

        public void SaveToFile(string Location) 
        {
            document.AppendChild(initiativeDateNode);
            foreach(KeyValuePair<string,List<XmlAttribute>> element in nodeDictionary)
            {
                XmlNode _element = DocumentContainsElement(element.Key);
                if (_element == null)
                {
                    _element = document.CreateElement(element.Key);
                }
                foreach(XmlAttribute attr in element.Value)
                {
                    _element.Attributes.Append(attr);
                }
                initiativeDateNode.AppendChild(_element);
            }
            document.Save(Console.Out);
            document.Save(Location);
            ResetDocument();
        }

        public List<XElement> ReadFromFile(string Location) 
        {
            XDocument xdoc = XDocument.Load(Location);
            if (xdoc != null)
            {
                return xdoc.Root.Elements("Character").Descendants().ToList();
            }
            return null;
        }

        private List<XmlAttribute> GetElementAttributes(string ElementName) 
        {
            if (!nodeDictionary.ContainsKey(ElementName))
            {
                nodeDictionary.Add(ElementName, new List<XmlAttribute>());
            }
            return nodeDictionary[ElementName];
        }

        private void SetAttribute(List<XmlAttribute> Attributes, string Attribute, String Value)
        {
            XmlAttribute temp = Attributes.Find(item => item.Name == Attribute);
            if(temp == null)
            {
                temp = document.CreateAttribute(Attribute);
                Attributes.Add(temp);
            }
            if(Value != "")
            temp.Value = Value;
        }

        public void AddElement(string Element, string Attribute ,string Value)
        {
            Element = Element.Replace(" ", "_");
            SetAttribute(GetElementAttributes(Element), Attribute, Value);
        }

        public void AddProperty(string Element, string Value, string Description = " ")
        {
            // Grabs Element. Creates if Doesnt Exist
            Element = Element.Replace(" ", "_");
            XmlNode element = DocumentContainsElement(Element);
            if (element == null)
            {
                element = document.CreateElement(Element);
            }
            XmlNode valueElement = document.CreateElement(Value);

            // Ensure Unique properties
            foreach(XmlNode node in element.ChildNodes)
            {
                if (node.Name == valueElement.Name)
                {
                    return;
                }
            }

            element.AppendChild(valueElement);
            valueElement.AppendChild(document.CreateTextNode(Description));
            initiativeDateNode.AppendChild(element);
        }

        public XmlNode DocumentContainsElement(string Value)
        {
            foreach (XmlNode node in initiativeDateNode.ChildNodes)
            {
                // Ensure Unique elements
                if (node.Name == Value)
                {
                    return node;
                }
            }
            return null;
        }
    }
}
